﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Reflection;
using GameBase;

namespace MilitaryPluginInterface
{
    public class Factory : GameObject
    {
        public enum FACTORY_STATE
        {
            Idle,
            Producing,
            Destroyed
        }
        private FACTORY_STATE _state;

        private My2DSprite _idle;
        private My2DSprite _producing;
        private My2DSprite _destroyed;

        private List<IMilitary> _infantrys;
        private List<string> _queueProducing = new List<string>();
        private Vector2 _targetPosition;

        public Vector2 TargetPosition
        {
            get { return _targetPosition; }
            set 
            { 
                _targetPosition = value; 
            }
        }

        private float _rangeRegenHealth = GameBase.Constant.rangeRegenHealth;
        private float currentTimeProduceHero = 0;
        private Vector2 _center;

        public FACTORY_STATE State
        {
            get { return _state; }
            set 
            {
                _state = value;
                switch (_state)
                {
                    case FACTORY_STATE.Idle:
                        _currentState = _idle;
                        break;
                    case FACTORY_STATE.Producing:
                        _currentState = _producing;
                        break;
                    case FACTORY_STATE.Destroyed:
                        _currentState = _destroyed;
                        break;
                }
            }
        }

        public bool IsRight
        {
            get { return _isRight; }
            set
            {
                _isRight = value;
                _idle.IsRight = _isRight;
                _producing.IsRight = _isRight;
            }
        }

        public Vector2 Center
        {
            get { return _center; }
            set { _center = value; }
        }

        public float RangeRegenHealth
        {
            get { return _rangeRegenHealth; }
            set { _rangeRegenHealth = value; }
        }

        public override Vector2 Position
        {
            get { return base.Position; }
            set
            {
                base.Position = value;
                _idle.Position = _producing.Position = _destroyed.Position = _health.Position = value;
            }
        }

        public Factory(string imgStr, Vector2 pos, Vector2 targetPosition)
        {
            internalInit(imgStr, pos, targetPosition);
        }

        private void internalInit(string imgStr, Vector2 pos, Vector2 targetPosition)
        {
            _position = pos;
            _idle = new LoopSprite(imgStr + @"_idle", 1, pos, 0.8f, 1000);
            _producing = new LoopSprite(imgStr + @"_producing", 1, pos, 0.8f, 1000);
            _destroyed = new LoopSprite(imgStr + @"_destroyed", 1, pos, 0.8f, 1000);
            _targetPosition = targetPosition;
            _size = _idle.Size;
            State = FACTORY_STATE.Idle;

            _health = new HealthPotion(@"Resources/health", 1000);
            _health.Width = (int)(_idle.LstTexture[0].Width * _idle.Scale);
            _health.Position = pos;

            _center = pos + _idle.Size / 2;

            initAllInfantry();
        }

        private void initAllInfantry()
        {
            _infantrys = new List<IMilitary>();
            _infantrys.Add(new Hero(@"Resources/hero1", this.Position + this.Size / 2));
            ((Military)_infantrys[0]).Position = this.Position + this.Size / 2;

            loadMilitaryPlugin();

            produceRandomMilitary();

            _circleChosen = GameBase.Constant.content.Load<Texture2D>(@"Resources/circleFactory");
        }

        private void loadMilitaryPlugin()
        {
            string startupPath = System.IO.Directory.GetCurrentDirectory();
            string[] fileNames = System.IO.Directory.GetFiles(startupPath + @"\MilitaryPlugin", "*.plugin");
            foreach (string fileName in fileNames)
            {
                Assembly asm = Assembly.LoadFile(fileName);
                string className = fileName.Replace(startupPath + @"\MilitaryPlugin\", "") + ".MilitaryPlugin";
                className = className.Replace(".plugin", "");

                //IMilitary newMilitary = (IMilitary)Activator.CreateInstance(fileName, className);

                Type[] types = asm.GetTypes();
                foreach (Type type in types)
                {
                    if (type.FullName == className)
                    {
                        //IMilitary newMilitary = (IMilitary)Activator.CreateInstance(type, BindingFlags.CreateInstance |
                        //                                     BindingFlags.Public |
                        //                                     BindingFlags.Instance |
                        //                                     BindingFlags.OptionalParamBinding,
                        //                                     null, new Object[] { Type.Missing }, null);

                        IMilitary newMilitary = (IMilitary)Activator.CreateInstance(type);
                        newMilitary.init(@"Resources/snipper", _targetPosition);

                        _infantrys.Add(newMilitary);
                        break;
                    }
                }
            }
        }

        public void produceAnInfantry(string nameInfantry)
        {
            _queueProducing.Add(nameInfantry);
        }

        public Military produceHeroImmediately()
        {
            return (Military)_infantrys[0].clone();
        }

        public bool isDestroyed()
        {
            return _state == FACTORY_STATE.Destroyed;
        }

        public override void draw(GameTime gameTime, SpriteBatch spriteBatch, Color color)
        {
            spriteBatch.Draw(_circleChosen, new Vector2(Position.X, Position.Y + Size.Y - _circleChosen.Height), Color.Green);

            _currentState.draw(gameTime, spriteBatch,color);
            _health.draw(gameTime, spriteBatch,color);
        }

        public override void update(GameTime gameTime)
        {
            if (State == FACTORY_STATE.Destroyed)
            {
                _currentTotalTime += gameTime.ElapsedGameTime.Milliseconds;
                if (_currentTotalTime > GameBase.Constant.timeForDisappear * 1000)
                {
                    _teamOwner.Factories.Remove(this);
                }
                return;
            }

            if (_queueProducing.Count != 0)
            {
                State = FACTORY_STATE.Producing;

                _currentTotalTime += gameTime.ElapsedGameTime.Milliseconds;
                string nameInfantry = _queueProducing[0];
                int index = getInfantryIndex(nameInfantry);
                int produceTime = ((Military)_infantrys[index]).ProduceTime;

                if (_currentTotalTime > produceTime * 1000)
                {
                    _queueProducing.RemoveAt(0);

                    produceRandomMilitary();

                    _currentTotalTime = 0;
                    Military newInfantry = (Military)_infantrys[index].clone();
                    newInfantry.Position = this.Position + this.Size / 2;
                    newInfantry.FinalTarget = this.Position + this.Size / 2;
                    this.TeamOwner.addInfantry(newInfantry);
                    newInfantry.walkTo(_targetPosition);
                }
            }
            else
            {
                State = FACTORY_STATE.Idle;
            }

            if (_teamOwner.Hero.isDead())
            {
                currentTimeProduceHero += gameTime.ElapsedGameTime.Milliseconds;
                if (currentTimeProduceHero >= _teamOwner.Hero.ProduceTime * 1000)
                {
                    currentTimeProduceHero = 0;
                    _teamOwner.Hero.respawn(this._targetPosition);
                }
            }

            _currentState.update(gameTime);
        }

        private void produceRandomMilitary()
        {
            //double factor = Constant.random.NextDouble();
            //if (factor >= 0.8f)
            //    _queueProducing.Add(@"Tank");
            //else if (factor > 0.5f){}
            //    _queueProducing.Add(@"Snipper");
            //else
            //    _queueProducing.Add(@"Soldier");
            if (_infantrys.Count - 1 == 0)
                return;
            int i = Constant.random.Next() % (_infantrys.Count - 1);
            _queueProducing.Add(_infantrys[i + 1].getName());
        }

        private int getInfantryIndex(string infantryName)
        {
            for (int i = 0; i < _infantrys.Count; i++)
            {
                if (infantryName == _infantrys[i].getName())
                    return i;
            }
            return -1;
        }

        public void beAttacked(Military military)
        {
            float damage = military.StrengthAttack;
            _health.Health -= (int)damage;
            if (_health.Health <= 0)
            {
                _state = FACTORY_STATE.Destroyed;
            }
        }
    }
}
